<?php

namespace App\Http\Controllers;

use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use stdClass;

class Controller extends BaseController
{
    use AuthorizesRequests, DispatchesJobs, ValidatesRequests;

    // 构建表单字段
    protected function build_form($fields, $default = null)
    {
        if (empty($fields)) return;
        $res = '';
        $btn_count = 0;
        foreach ((array)$fields as $field) {
            $name = isset($field['name']) ? $field['name'] : '';
            $label = isset($field['label']) ? $field['label'] : '';
            $type = isset($field['type']) ? $field['type'] : 'text';
            $layui = isset($field['layui']) ? $field['layui'] : 'form-item';
            $class = isset($field['class']) ? $field['class'] : (in_array($type, ['textarea', 'editor', 'button', 'submit']) ? 'block' : ($layui === 'inline' ? 'block' : 'inline'));
            $style = isset($field['style']) && $field['style'] ? ($type === 'editor' ? (' style="display:none;' . $field['style'] . '"') : (' style="' . $field['style'] . '"')) : ($type === 'editor' ? ' style="display:none;"' : '');
            $value = isset($default->$name) ? $default->$name : (isset($field['value']) ? $field['value'] : ($type === 'number' ? 0 : ($type === 'checkbox' ? [] : '')));
            $placeholder = isset($field['placeholder']) ? ' placeholder="' . $field['placeholder'] . '"' : '';
            $verify = isset($field['verify']) ? ' lay-verify="' . $field['verify'] . '"' : '';
            $required = isset($field['required']) ? ($type === 'select' ? ' lay-verify="required"' : ' required lay-verify="required"') : '';
            $desc = isset($field['desc']) ? '<div class="layui-form-mid layui-word-aux">' . $field['desc'] . '</div>' : '';
            $step = isset($field['step']) ? ' step="' . $field['step'] . '"' : '';
            $min = isset($field['min']) ? ' min="' . $field['min'] . '"' : '';
            $max = isset($field['max']) ? ' max="' . $field['max'] . '"' : '';
            $rows = isset($field['rows']) ? ' rows="' . $field['rows'] . '"' : '';
            $autocomplete = isset($field['autocomplete']) ? ' autocomplete="' . $field['autocomplete'] . '"' : '';
            $sep = isset($field['sep']) ? $field['sep'] : '';
            $filter = isset($field['filter']) ? $field['filter'] : 'submit';
            $options = isset($field['options']) ? $field['options'] : [];
            if ($type === 'hidden') {
                $res .= '<input type="' . $type . '" name="' . $name . '" value="' . $value . '">';
            } elseif ($type === 'number') {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">
                                <input type="number" name="' .  $name . '" value="' .  $value . '"' .  $step . $min . $max . $verify . $required . $placeholder . $autocomplete . $style . ' class="layui-input">
                            </div>' .  $desc . '
                        </div>';
            } elseif ($type === 'select') {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' .  $label . '</label>
                            <div class="layui-input-' .  $class . '">
                                <select name="' .  $name . '"' .  $verify . $required . $style . '>';
                foreach ($options as $k => $v) {
                    $res .= '<option value="' .  $k . '"' . ((string)$k === (string)$value ? ' selected' : '') . '>' .  $v . '</option>';
                }
                $res .= '</select>
                            </div>' .  $desc . '
                        </div>';
            } elseif ($type === 'radio') {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' .  $label . '</label>
                            <div class="layui-input-' .  $class . '">';
                foreach ($options as $k => $v) {
                    $res .= '<input type="radio" name="' .  $name . '"' . ((string)$k === (string)$value ? ' checked' : '') . ' value="' .  $k . '" title="' .  $v . '">';
                }
                $res .= '</div>' .  $desc . '
                        </div>';
            } elseif ($type === 'switch') {
                $res .= '<div class="layui-' . $layui . '">
                        <label class="layui-form-label">' .  $label . '</label>
                        <div class="layui-input-' .  $class . '">
                        <input type="checkbox" name="' . $name . '"' . ($value === 'on' ? 'checked' : '') . ' lay-text="ON|OFF" lay-skin="switch">
                        </div>
                    </div>';
            } elseif ($type === 'checkbox') {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">';
                foreach ($options as $k => $v) {
                    $res .= '<input type="checkbox" name="' . $name . '[]" value="' . $k . '" lay-skin="primary" title="' . $v . '"' . (in_array($k, (array)$value) ? ' checked' : '') . '>';
                    $res .= $k === count($options) ? '' : $sep;
                }
                $res .= '</div>' . $desc . '
                        </div>';
            } elseif ($type === 'textarea') {
                $res .= '<div class="layui-' . $layui . ' layui-form-text">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">
                                <textarea name="' . $name . '"' . $placeholder . $rows . $style . ' class="layui-textarea">' . $value . '</textarea>
                            </div>
                        </div>';
            } elseif ($type === 'upload') {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">
                                <input type="text" name="' . $name . '" value="' . $value . '"' . $verify . $required . $placeholder . $autocomplete . $style . ' class="layui-input">
                                <div class="layui-upload-list">' . (preg_match('/\/.+?\.(gif|jpg|jpeg|png|bmp|webp|psd|svg|tiff)$/i', $value) ? '<img src="' . $value . '" alt="Preview" style="width:92px" />' : '') . '</div>
                            </div>
                            <div class="layui-form-mid layui-word-aux layui-btn layui-btn-primary btn-upload" style="padding:0 10px">&nbsp;&nbsp;&nbsp;上传&nbsp;&nbsp;&nbsp;</div>
                        </div>';
            } elseif ($type === 'editor') {
                $res .= '<div class="layui-' . $layui . ' layui-form-text">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">
                                <textarea id="' . $name . '" class="layui-textarea"' . $style . '>' . $value . '</textarea>
                            </div>
                        </div>';
            } elseif ($type === 'tree') {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">
                                <div id="' . ltrim(ltrim($options['elem'] ?? 'trees', '#'), '.') . '"></div>
                            </div>' . $desc . '
                        </div>';
            } elseif ($type === 'html') {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">
                                ' . $value . '
                            </div>' . $desc . '
                        </div>';
            } elseif (in_array($type, ['submit', 'reset', 'button'])) {
                $btn_count++;
                if ($btn_count === 1) {
                    $res .= '<div class="layui-' . $layui . '">';
                    $res .= ($layui !== 'inline') ? '<div class="layui-input-' . $class . '">' : '';
                }
                $res .= '<button type="' . $type . '"' . $style . ' lay-' . $type . ' lay-filter="' . $filter . '" class="layui-btn' . (isset($field['btn']) ? ' layui-btn-' . $field['btn'] : '') . '">' . $value . '</button> ';
                if ($btn_count === count(array_filter($fields, function ($item) {
                    return isset($item['type']) && in_array($item['type'], ['submit', 'reset', 'button']);
                }))) {
                    $res .= ($layui !== 'inline') ? '</div>' : '';
                    $res .= $desc;
                    $res .= '</div>';
                }
            } else {
                $res .= '<div class="layui-' . $layui . '">
                            <label class="layui-form-label">' . $label . '</label>
                            <div class="layui-input-' . $class . '">
                                <input type="' . $type . '" name="' . $name . '" value="' . $value . '"' . $verify . $required . $placeholder . $autocomplete . $style . ' class="layui-input">
                            </div>' . $desc . '
                        </div>';
            }
        }
        return $res;
    }

    // 构建动作脚本
    protected function build_script($fields, $args = [])
    {
        if (empty($fields)) return;
        $res = '';
        $params = ['element'];
        $args = array_merge(['upload' => '/uploads', 'url' => '/index', 'reload' => 'location'], $args);
        $uploads = $editors = $options = $values = $submits = [];
        foreach ($fields as $field) {
            // 上传
            if (isset($field['type']) && $field['type'] === 'upload' && isset($field['name'])) {
                if (!in_array($field['name'], $uploads)) array_push($uploads, $field['name']);
                if (!in_array('upload', $params)) array_push($params, 'upload');
            }
            // 富文本
            if (isset($field['type']) && $field['type'] === 'editor' && isset($field['name'])) {
                if (!in_array($field['name'], $editors)) array_push($editors, $field['name']);
                if (!in_array('layedit', $params)) array_push($params, 'layedit');
                if (!in_array('upload', $params)) array_push($params, 'upload');
            }
            // 树形组件
            if (isset($field['type']) && $field['type'] === 'tree' && isset($field['options']) && $field['options']) {
                if (!in_array('tree', $params)) {
                    array_push($params, 'tree');
                    array_push($options, $field['options']);
                    if (isset($field['value'])) array_push($values, $field['value']);
                }
            }
            // 监听事件
            if (isset($field['type']) && $field['type'] === 'submit') {
                $filter = isset($field['filter']) ? $field['filter'] : 'submit';
                if (!in_array($filter, $submits)) array_push($submits, $filter);
                if (!in_array('form', $params)) array_push($params, 'form');
            }
        }
        // 表单事件
        $res .= 'layui.use(["' . implode('","', $params) . '"], function() {
            let $ = layui.jquery, element = layui.element;' . "\n";
        if (in_array('layedit', $params) || in_array('upload', $params)) {
            $res .= 'let token = $("input[name=\'_token\']").val();' . "\n";
        }
        // 富文本上传
        if (in_array('layedit', $params)) {
            $res .= 'let layedit = layui.layedit;' . "\n";
            $res .= 'let editors = [];' . "\n";
            $res .= 'let _editors = ' . json_encode($editors) . ";\n";
            $res .= 'layedit.set({
                uploadImage: {
                    url: "' . $args['upload'] . '?_token=" + token, //接口url
                    type: "post", //默认post
                }
            });
            for (let editor of _editors) {
                editors[editor] = layedit.build(editor);
            }' . "\n";
        }
        // 上传框
        if (in_array('upload', $params)) {
            $res .= 'let upload = layui.upload;' . "\n";
            $res .= 'let uploadInst = upload.render({
                elem: ".btn-upload",
                url: "' . $args['upload'] . '",
                data: {
                    _token: token
                },
                before: function(obj) {
                    layer.load();
                },
                done: function(res, index, upload) {
                    layer.closeAll("loading");
                    if (res.code > 0) {
                        return layer.msg("上传失败");
                    }
                    //上传成功
                    $(this.item).prev().find(".layui-input").val(res.data.src);
                    if (/\.(gif|jpg|jpeg|png|bmp|webp|psd|svg|tiff)$/gi.test(res.data.src)) {
                        $(this.item).prev().find(".layui-upload-list").html("<img src=\'" + res.data.src + "\' alt=\'Preview\' style=\'width:92px\' />");
                    }
                },
                error: function(index, upload) {
                    layer.closeAll("loading");
                }
            });' . "\n";
        }
        // 树形组件
        if (in_array('tree', $params)) {
            $res .= 'let tree = layui.tree;' . "\n";
            foreach ($options as $key => $option) {
                $res .= 'let treeInst' . ($key === 0 ? '' : "_{$key}") . ' = tree.render({' . "\n";
                foreach ($option as $k => $v) {
                    if (is_null(json_decode($v))) {
                        $res .= $k . ': "' . $v . '",';
                    } else {
                        $res .= $k . ': ' . $v . ',';
                    }
                }
                $res .= '});' . "\n";
            }
            foreach ($options as $key => $option) {
                if (isset($option['id']) && $option['id'] && isset($values[$key])) {
                    $res .= 'tree.setChecked("' . $option['id'] . '", ' . $values[$key] . ');' . "\n";
                }
            }
            $res .= 'function setIds(data, ids = []) {
                data.forEach(elem => {
                    ids.push(elem.id);
                    setIds(elem.children, ids);
                });
                return ids;
            }' . "\n";
            $res .= 'function checkedIds(data, ids = []) {
                data.forEach(elem => {
                    ids.push(elem.id);
                    checkedIds(elem.children, ids);
                });
                return ids;
            }' . "\n";
        }
        // 监听提交
        if (in_array('form', $params)) {
            $res .= 'let form = layui.form;' . "\n";
            $res .= 'let parentIndex = parent.layer.getFrameIndex(window.name);' . "\n";
            if (count(array_filter($fields, function ($item) {
                return isset($item['type']) && $item['type'] === 'button' && isset($item['filter']) && $item['filter'] === 'cancel';
            }))) {
                $res .= '$("button[lay-filter=\'cancel\']").click(function(){
                    if (typeof parentIndex !== "undefined") {
                        parent.layer.close(parentIndex);
                    } else {
                        location.href = "' . $args['reload'] . '";
                    }
                });' . "\n";
            }
            foreach ($submits as $submit) {
                $res .= 'form.on("submit(' . $submit . ')", function(data) {' . "\n";
                if (in_array('layedit', $params)) {
                    $res .= 'if (typeof _editors !== "undefined" && typeof editors !== "undefined") {
                        for (let editor in editors) {
                            data.field[editor] = layedit.getContent(editors[editor]);
                        }
                    }' . "\n";
                }
                if (in_array('tree', $params)) {
                    foreach ($options as $key => $option) {
                        if (isset($option['id']) && $option['id'] && isset($option['showCheckbox']) && $option['showCheckbox']) {
                            $res .= 'data.field.' . $option['id'] . ' = checkedIds(tree.getChecked("' . $option['id'] . '"));' . "\n";
                        }
                    }
                }
                $res .= '$.' . ($submit === 'submit' ? 'post' : 'get') . '("' . $args['url'] . '", data.field, function(res) {
                        if (res.code) {
                            return layer.alert(res.msg, {
                                icon: 2
                            });
                        }
                        layer.alert(res.msg, {
                            icon: 1
                        });' . "\n";
                if (isset($args['reload']) && $args['reload']) {
                    if (false !== strpos($args['reload'], 'location')) {
                        $res .= 'setTimeout(function() {
                            ' . $args['reload'] . '.reload();
                        }, 1000);' . "\n";
                    } elseif (false !== strpos($args['reload'], '/')) {
                        $res .= 'location.href = "' . $args['reload'] . '"';
                    } else {
                        $res .= 'if (typeof parentIndex !== "undefined") {
                            setTimeout(function() {
                                if (parent.layui.table.index) {
                                    parent.layui.table.reload("' . $args['reload'] . '");
                                }
                                parent.layer.close(parentIndex);
                            }, 1000);
                        }' . "\n";
                    }
                }
                $res .= '}, "json");
                    return false;
                });' . "\n";
            }
        }
        $res .= "});\n";
        return $res;
    }

    // 表单数据校验
    protected function check($fields, $request)
    {
        $res = [];
        foreach ($fields as $field) {
            if (!isset($field['name']) || trim($field['name']) === '') continue;
            $name = $field['name'];
            $label = isset($field['label']) ? $field['label'] : $name;
            $type = isset($next['type']) ? $next['type'] : 'text';
            if (!$name) {
                return $this->errMsg(1, $label . '字段缺失');
            }
            if (isset($field['required']) || isset($field['verify'])) {
                if (!isset($request->$name) || (isset($request->$name) && trim($request->$name) === '')) {
                    return $this->errMsg(1, $label . '选项必填');
                }
            }
            $value = $request->$name ?? null;
            if (!is_null($value) && is_string($value) && $type !== 'password') {
                $value = trim($value);
            }
            $res[$name] = $value;
        }
        return $res;
    }

    // 无限层级递归
    protected function levels($datas, $pid = 0, $level = 0)
    {
        $res = [];
        foreach ($datas as $data) {
            if ($data->pid === $pid) {
                $data->level = $level;
                $data->children = $this->levels($datas, $data->id, $level + 1);
                $res[] = $data;
            }
        }
        return $res;
    }

    // 无限层级树
    protected function trees($datas, $pid = 0, $level = 0)
    {
        $res = array();
        foreach ($datas as $data) {
            if ($data->pid == $pid) {
                $data->level = $level;
                $res[] = $data;
                $res = array_merge($res, $this->trees($datas, $data->id, $level + 1));
            }
        }
        return $res;
    }

    // 父子层级关系
    protected function parents($datas, $id = 0)
    {
        $res = array();
        foreach ($datas as $data) {
            if ($data->id == $id) {
                $res[] = $data;
                $res = array_merge($res, $this->parents($datas, $data->pid));
            }
        }
        return $res;
    }

    // 子数据平级
    protected function plates($menus, &$res = [])
    {
        foreach ($menus as $menu) {
            if (isset($menu->children)) {
                $temp = $menu->children;
                unset($menu->children);
                $res[] = $menu;
                $this->plates($temp, $res);
            } else {
                $res[] = $menu;
            }
        }
        return $res;
    }

    // 数组指针无限极菜单
    // 无限极菜单
    protected function buildTree($menus)
    {
        $tree = [];
        foreach ($menus as $menu) {
            if (isset($menus[$menu['pid']])) {
                $menus[$menu['pid']]['children'][] = &$menus[$menu['id']];
            } else {
                $tree[] = &$menus[$menu['id']];
            }
        }
        return $tree;
    }

    // 让子菜单平级
    protected function formatTree($menus, &$res = [])
    {
        foreach ($menus as $menu) {
            if (isset($menu['children'])) {
                $temp = $menu['children'];
                unset($menu['children']);
                $res[] = $menu;
                $this->formatTree($temp, $res);
            } else {
                $res[] = $menu;
            }
        }
        return $res;
    }

    // 错误消息
    protected function errMsg($code, $msg, $data = [], $files = [])
    {
        if (request()->ajax()) {
            return json_encode(['code' => $code, 'msg' => $msg, 'data' => $data, 'files' => $files]);
        }
        exit("<p style='text-align:center'>$msg</p>");
    }
}
